package cn.bonoon.kernel.expression;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.util.Assert;

import cn.bonoon.kernel.annotations.QueryExpression;
import cn.bonoon.kernel.annotations.QueryJoin;
import cn.bonoon.kernel.expression.resolver.BaseExpressionResolver;
import cn.bonoon.kernel.expression.results.RequestExpressionValue;

public class StandardExpressionParser implements ExpressionParser{
	
	private final static char S = '{', E = '}';
	
	private final StringBuilder expression = new StringBuilder();
	private final List<ExpressionValue> values = new ArrayList<>();
	private final List<QueryParameter> parameters = new ArrayList<>();
	private final IExpressionResolver expressionResolver;
	
	private Map<String, String> joinMapped;
	
	public StandardExpressionParser(){
		this.expressionResolver = BaseExpressionResolver.factory();
	}
	
	public void value(ExpressionValue eValue){
		values.add(eValue);
	}
	
	public void parameter(QueryParameter parameter){
		parameters.add(parameter);
	}
	
	/**
	 * 用于界面上的处理，生成从界面到控制器的传递语句
	 * @return
	 */
	public List<QueryParameter> getParameters() {
		return parameters;
	}
	
	private void _parse(String query, IExpressionResolver expressionResolver)throws Exception{
		expression.append(" and ");
		int i = 0;
		char[] chs = query.toCharArray();
		int ol = chs.length;
		while(i < ol - 1){
			char c0 = chs[i++];
			
			if(c0 == S){
				if(chs[i] == S){
					i++;
					expression.append(c0);
				}else{
					//需要替换的属性的开始位置
					int sp = i;
					
					while(i < ol && chs[i++] != E);
					//i为最近的一个'}'的位置
					int l = i - sp;
					if(i < ol || chs[i - 1] == E){
						l--;
					}
					if(l > 0){
						String valueExpression = new String(chs, sp, l).trim();
						if(!expressionResolver.resolver(valueExpression, this)){
							//这里是没有进行定义的表达式，则认为该值直接使用velocity进行赋值
							values.add(new RequestExpressionValue(this, valueExpression));
						}
					}//else 只有"{}"的情况或以"{"结束的情况
				}
			}else{
				if(c0 == E && chs[i] == E){
					i++;
				}
				expression.append(c0);
			}
		}
		while(i < ol){
			expression.append(chs[i++]);
		}
	}
	
	public StringBuilder getExpression() {
		return expression;
	}

	public void addExpression(QueryExpression expression) throws Exception{
		addExpression(expression, expressionResolver);
	}

	public void addExpression(QueryExpression expression, IExpressionResolver expressionResolver) throws Exception{
		if(expression.joins().length > 0){
			if(null == joinMapped){
				joinMapped = new HashMap<>();
			}
			for(QueryJoin je : expression.joins()){
				joinMapped.put(je.value(), je.alias());
			}
		}
		_parse(expression.value(), expressionResolver);
	}

	public void addExpression(String expression) throws Exception{
		Assert.notNull(expression, "表达式不允许为空！");
		_parse(expression, expressionResolver);
	}

	public void addExpression(String expression, String value) throws Exception{
		Assert.notNull(expression, "表达式不允许为空！");
		this.expression.append(" and ").append(expression);
		this.values.add(new RequestExpressionValue(this, value, "J"));
		parameter(new QueryParameter(value, value, QueryParameterType.INPUT));
	}

	@Override
	public Map<String, String> joinMapped() {
		return joinMapped;
	}

	@Override
	public String where() {
		return expression.toString();
	}

	@Override
	public ExpressionValue[] values() {
		return values.toArray(new ExpressionValue[values.size()]);
	}

	public void expression(String exp) {
		this.expression.append(" and ").append(exp);
	}
}
